package com.upb.webserver.order;

import com.upb.webserver.common.constant.Constant;
import com.upb.webserver.common.enums.OrderTypeEnum;
import com.upb.webserver.common.enums.PlatformEnum;
import com.upb.webserver.common.exception.WebServerException;
import com.upb.webserver.common.pojo.order.ReqAddWorkOrderOfCrossChainVO;
import com.upb.webserver.common.pojo.order.ReqAddWorkOrderOfNewApplicationVO;
import com.upb.webserver.common.pojo.order.ReqAddWorkOrderOfNewChainVO;
import com.upb.webserver.common.returncode.ConstantCode;
import com.upb.webserver.common.tools.JsonUtils;
import com.upb.webserver.company.CompanyDeveloperService;
import com.upb.webserver.dao.entity.TbWorkOrder;
import com.upb.webserver.dao.mapper.TbOrgMapper;
import com.upb.webserver.org.OrgManager;
import com.upb.webserver.org.OrgService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

import static com.upb.webserver.common.constant.Constant.ORDER_TYPE_LIST_NEW_APP;

@Slf4j
@Service
public class BaseOrderService {
    @Autowired
    private TbOrgMapper orgMapper;
    @Autowired
    private OrgManager orgManager;
    @Autowired
    private OrgService orgService;
    @Autowired
    private CompanyDeveloperService companyDeveloperService;

    /**
     * @param workOrder
     */
    public void verifyAllOrgHasCompleted(TbWorkOrder workOrder) {
        if (!hasAllOrgCompleted(workOrder)) {
            log.warn("fail exec method [checkOrgCompletedResult]");
            throw new WebServerException(ConstantCode.SOME_ONE_HAVE_NOT_COMPLETED_WORK_ORDER);
        }
    }


    /**
     * @param workOrder
     * @return
     */
    public boolean hasAllOrgCompleted(TbWorkOrder workOrder) {
        log.warn("start exec method [hasAllOrgCompleted]. workOrder:{}", JsonUtils.objToString(workOrder));
        Byte type = workOrder.getType();
        long countOrgNotCompleted = 0;
        if (type == OrderTypeEnum.NEW_CHAIN_FABRIC.getValue()) {
            ReqAddWorkOrderOfNewChainVO chainDetailVO = JsonUtils.stringToObj(workOrder.getDetail(), ReqAddWorkOrderOfNewChainVO.class);
            countOrgNotCompleted = chainDetailVO.getFabricPeerOrgList().stream()
                    .filter(o -> CollectionUtils.isEmpty(o.getPeerNodeList())).count();
        } else if (type == OrderTypeEnum.NEW_CHAIN_FISCO.getValue()) {
            ReqAddWorkOrderOfNewChainVO chainDetailVO = JsonUtils.stringToObj(workOrder.getDetail(), ReqAddWorkOrderOfNewChainVO.class);
            countOrgNotCompleted = chainDetailVO.getFiscoOrgList().stream()
                    .filter(o -> CollectionUtils.isEmpty(o.getFiscoHostList())).count();
        } else if (ORDER_TYPE_LIST_NEW_APP.contains(type)) {
            ReqAddWorkOrderOfNewApplicationVO appDetailVO = JsonUtils.stringToObj(workOrder.getDetail(), ReqAddWorkOrderOfNewApplicationVO.class);
            countOrgNotCompleted = appDetailVO.getConfirmOrgList().stream().filter(co -> co.getConfirmFlag() == false).count();
        } else if(type==OrderTypeEnum.JOIN_CROSS_CHAIN.getValue()){
            ReqAddWorkOrderOfCrossChainVO orderDetailVO = JsonUtils.stringToObj(workOrder.getDetail(), ReqAddWorkOrderOfCrossChainVO.class);
            countOrgNotCompleted = orderDetailVO.getApplicationOrgCollection().stream().filter(o ->  CollectionUtils.isEmpty(o.getApplicationIdCollection())).count();
        }else {
            log.error("fail exec method [hasAllOrgCompleted]. not support orderType:{}", type);
            return false;
        }

        boolean hadAllOrgComplete = true;
        if (countOrgNotCompleted > 0) {
            hadAllOrgComplete = false;
            log.info("finish exec method [hasAllOrgCompleted]. countOrgNotCompleted:{} hadAllOrgComplete:{}", countOrgNotCompleted, hadAllOrgComplete);
        }
        return hadAllOrgComplete;
    }

    /**
     * @param workOrder
     */
    public List<Integer> getAllDeveloperIdFromWorkOrder(TbWorkOrder workOrder) {
        log.info("start exec method [getAllDeveloperIdFromWorkOrder].");
        List<Integer> orgIdList = getAllOrgIdFromWorkOrder(workOrder);
        List<Integer> developerIdList = orgService.listDeveloperIdByOrgIdList(orgIdList);
        log.info("success exec method [getAllOrgIdFromWorkOrder]. result:{}", JsonUtils.objToString(developerIdList));
        return developerIdList;

    }

    /**
     * @param workOrder
     * @return
     */
    public List<Integer> getAllOrgIdFromWorkOrder(TbWorkOrder workOrder) {
        log.info("start exec method [getAllOrgIdFromWorkOrder].");
        final List<Integer> orgIdList = new ArrayList<>();
        Byte orderType = workOrder.getType();
        if (orderType == OrderTypeEnum.NEW_CHAIN_FABRIC.getValue()) {
            ReqAddWorkOrderOfNewChainVO chainDetailVO = JsonUtils.stringToObj(workOrder.getDetail(), ReqAddWorkOrderOfNewChainVO.class);
            chainDetailVO.getFabricPeerOrgList().stream().forEach(o -> orgIdList.add(o.getOrgId()));
            chainDetailVO.getFabricOrderOrgList().stream().forEach(o -> orgIdList.add(o.getOrgId()));
        } else if (orderType == OrderTypeEnum.NEW_CHAIN_FISCO.getValue()) {
            ReqAddWorkOrderOfNewChainVO chainDetailVO = JsonUtils.stringToObj(workOrder.getDetail(), ReqAddWorkOrderOfNewChainVO.class);
            chainDetailVO.getFiscoOrgList().stream().forEach(o -> orgIdList.add(o.getOrgId()));
        } else if (orderType == OrderTypeEnum.NEW_APPLICATION_FABRIC.getValue() || orderType == OrderTypeEnum.NEW_APPLICATION_FISCO.getValue()) {
            ReqAddWorkOrderOfNewApplicationVO appDetail = JsonUtils.stringToObj(workOrder.getDetail(), ReqAddWorkOrderOfNewApplicationVO.class);
            appDetail.getConfirmOrgList().stream().forEach(o -> orgIdList.add(o.getOrgId()));
        } else {
            log.warn("fail exec method [getAllOrgIdFromWorkOrder] ,not config orderType:{}", orderType);
        }

        log.info("success exec method [getAllOrgIdFromWorkOrder]. result:{}", JsonUtils.objToString(orgIdList));
        return orgIdList;
    }



    /**
     * @param workOrder
     * @return
     */
    public String getCreatorOrgName(TbWorkOrder workOrder) {
        log.debug("start exec method [getCreatorOrgName]. workOrder:{}", JsonUtils.objToString(workOrder));

        if (PlatformEnum.DEV_OPS.getId() == workOrder.getCreateFromPlatform()) {
            log.debug("finish exec method [getCreatorOrgName], result:{}", Constant.DEV_OPS_ADMIN_NAME_ZH);
            return Constant.DEV_OPS_ADMIN_NAME_ZH;
        }

        int createDeveloper = workOrder.getCreateBy();
        int createCompanyId = companyDeveloperService.selectCompanyIdByDeveloperId(createDeveloper);
        Byte type = workOrder.getType();
        Integer createOrgId = null;
        if (type == OrderTypeEnum.NEW_CHAIN_FABRIC.getValue()) {
            ReqAddWorkOrderOfNewChainVO chainDetailVO = JsonUtils.stringToObj(workOrder.getDetail(), ReqAddWorkOrderOfNewChainVO.class);
            createOrgId = chainDetailVO.getFabricPeerOrgList().stream().filter(fo -> fo.getCompanyId() == createCompanyId).findFirst().map(o -> o.getOrgId()).orElse(null);
        } else if (type == OrderTypeEnum.NEW_CHAIN_FISCO.getValue()) {
            ReqAddWorkOrderOfNewChainVO chainDetailVO = JsonUtils.stringToObj(workOrder.getDetail(), ReqAddWorkOrderOfNewChainVO.class);
            createOrgId = chainDetailVO.getFiscoOrgList().stream().filter(fo -> fo.getCompanyId() == createCompanyId).findFirst().map(o -> o.getOrgId()).orElse(null);
        } else if (type == OrderTypeEnum.NEW_APPLICATION_FABRIC.getValue() || type == OrderTypeEnum.NEW_APPLICATION_FISCO.getValue()) {
            ReqAddWorkOrderOfNewApplicationVO appDetail = JsonUtils.stringToObj(workOrder.getDetail(), ReqAddWorkOrderOfNewApplicationVO.class);
            createOrgId = appDetail.getConfirmOrgList().stream().filter(fo -> fo.getCompanyId() == createCompanyId).findFirst().map(o -> o.getOrgId()).orElse(null);
        }else if (OrderTypeEnum.JOIN_CROSS_CHAIN.getValue() == type) {
            ReqAddWorkOrderOfCrossChainVO orderDetail = JsonUtils.objToJavaBean(workOrder.getDetail(), ReqAddWorkOrderOfCrossChainVO.class);
            createOrgId = orderDetail.getApplicationOrgCollection().stream().filter(fo -> fo.getCompanyId() == createCompanyId).findFirst().map(o -> o.getOrgId()).orElse(null);
        }else {
            log.warn("finish exec method [getTargetNameOfWorkOrder] ,not support workOrderType:{}", type);
            return null;
        }

        String creatorOrgName = orgMapper.selectNameByPrimaryKey(createOrgId);
        log.debug("finish exec method [getCreatorOrgName]. result:{}", creatorOrgName);

        return creatorOrgName;
    }




}
